﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using FT.Architecture.Entities;
using FT.Architecture.Utils.Reflection;

namespace FT.Architecture.NHibernate.Context
{
    /// <summary>
    /// Build a HQL query from a type and members to left join fetch.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <typeparam name="TId"></typeparam>
    internal class QueryBuilderEngine<T, TId> where T : IGenericEntity<TId>
    {
        private readonly Expression<Func<T, object>>[] _expressions;

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="expressions"></param>
        public QueryBuilderEngine(params Expression<Func<T, object>>[] expressions)
        {
            _expressions = expressions;
        }

        /// <summary>
        /// Returns the HQL query
        /// </summary>
        /// <returns></returns>
        public string BuildQuery()
        {
            var query = new StringBuilder();

            Type entityType = typeof(T);
            query.Append("from " + entityType.Name + " _entity");

            int i = 0;
            foreach (Expression<Func<T, object>> expression in _expressions)
            {
                BuildSubExpression(expression, query, ref i);
            }

            return query.ToString();
        }

        private static void BuildSubExpression(Expression<Func<T, object>> expression, StringBuilder builder, ref int i)
        {
            IEnumerable<PropertyInfo> propertyInfos = Reflection.GetProperties(expression);
            propertyInfos = propertyInfos.Reverse();

            string itemName = "_entity";
            foreach (PropertyInfo info in propertyInfos)
            {
                builder.Append(" left join fetch " + itemName + "." + info.Name + " _item" + i);
                itemName = "_item" + i;
                i++;
            }
        }
    }
}
